package com.kqzz.common.config;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskDecorator;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import com.google.common.util.concurrent.ThreadFactoryBuilder;


@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer{

	private static int cpuNum = Runtime.getRuntime().availableProcessors();
	
    @Bean("asyncExecutor")
    public Executor asyncExecutor() {
    	// cpu密集型 最大线程数=cpu个数
    	// io密集型   最大线程数>io任务数
    	/*
    	 * 排查死锁 使用命令行指令
    	 * jps -l      ->  查看jvm中的进程
    	 * jstack pid  ->  根据进程号查看堆栈信息
		 * taskkill -pid xxx /f (linux: kill -9 xxx)  -> 根据pid进程号结束该进程
		 * jinfo pid   ->   查看进程的概要信息
		 */
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(cpuNum*2);
        //配置最大线程数
        executor.setMaxPoolSize(cpuNum*4);
        //配置队列大小
        executor.setQueueCapacity(1000);
        // 允许线程的空闲时间60秒：当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60); 
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("asyncExecutor-");
        // 设置是否等待计划任务在关闭时完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置此执行器应该阻止的最大秒数
        executor.setAwaitTerminationSeconds(60);
        // 增加 TaskDecorator 属性的配置
        executor.setTaskDecorator(new ContextDecorator());
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        /* new ThreadPoolExecutor.AbortPolicy() 抛弃任务抛出异常
		 * new ThreadPoolExecutor.CallerRunsPolicy() 不在新线程中执行任务，而是有调用者所在的线程来执行
		 * new ThreadPoolExecutor.DiscardOldestPolicy() 不抛弃任务，尝试删除最早的任务
		 * new ThreadPoolExecutor.DiscardPolicy() 抛弃任务不产生异常
		 */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
//    @Bean("asyncExecutor")
    public ExecutorService asyncDeferredExecutor() {
    	ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("asyncExecutor-%d").build();
	    ExecutorService fixed_thread_pool = new ThreadPoolExecutor(
	    		cpuNum*2, //10,  // 核心线程数
	    		cpuNum*4, //20, // 最大线程池
	    		60L, // 等待时间
	    		TimeUnit.SECONDS,
	    		new LinkedBlockingQueue<Runnable>(100), // 队列
	    		namedThreadFactory,new ThreadPoolExecutor.CallerRunsPolicy());
        return fixed_thread_pool;
    }
    
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }


    /**
     * 任务装饰器
     */
    class ContextDecorator implements TaskDecorator {
        @Override
        public Runnable decorate(Runnable runnable) {
            try {
                // 在非web下访问了RequestContextHolder.currentRequestAttributes()导致对象为空，强制对象返回
                RequestAttributes context = RequestContextHolder.currentRequestAttributes();
                return () -> {
                    try {
                        RequestContextHolder.setRequestAttributes(context);
                        runnable.run();
                    } finally {
                        RequestContextHolder.resetRequestAttributes();
                    }
                };
            } catch (IllegalStateException e) {
                return runnable;
            }
        }
    }
}